#include "EpilBinaryExpressionCode.h"
#include "TCharSupport.h"
#include "EpilOutputHelper.h"
#include "EpilUnaryExpressionCode.h"
#include "EpilPointerHelper.h"


EpilBinaryExpressionCode::EpilBinaryExpressionCode( const EpilLexLocation & location )
: EpilExpressionCodeBase( location )
, m_operator( EBO_Invalid )
, m_leftExpr( NULL )
, m_rightExpr( NULL )
{
}


EpilBinaryExpressionCode::~EpilBinaryExpressionCode()
{
	EpilPointerHelper::SafeDelete( m_leftExpr );
	EpilPointerHelper::SafeDelete( m_rightExpr );
}


tstring EpilBinaryExpressionCode::ToEpilCode( int indent ) const
{
	tstringstream ret;
	int precedence = EpilOutputHelper::GetBinaryOperatorPrecedence( m_operator );

	bool isLeftNeedParentheses = false;
	if( m_leftExpr->GetType() == ECT_BinaryExpression )
	{
		EpilBinaryExpressionCode * binary = static_cast<EpilBinaryExpressionCode*>( m_leftExpr );
		int leftPrecedence = EpilOutputHelper::GetBinaryOperatorPrecedence( binary->GetOperator() );
		if( leftPrecedence < precedence )
		{
			isLeftNeedParentheses = true;
		}
	}
	else if( m_leftExpr->GetType() == ECT_UnaryExpression )
	{
		EpilUnaryExpressionCode * unary = static_cast<EpilUnaryExpressionCode*>( m_leftExpr );
		int leftPrecedence = EpilOutputHelper::GetUnaryOperatorPrecedence( unary->GetOperator() );
		if( leftPrecedence < precedence )
		{
			isLeftNeedParentheses = true;
		}
	}
	if( isLeftNeedParentheses )
	{
		ret << t("( ");
		ret << m_leftExpr->ToEpilCode();
		ret << t(" )");
	}
	else
	{
		ret << m_leftExpr->ToEpilCode();
	}
	
	ret << t(" ");
	ret << EpilOutputHelper::GetBinaryOperator( m_operator );
	ret << t(" ");

	bool isRightNeedParentheses = false;
	if( m_rightExpr->GetType() == ECT_BinaryExpression )
	{
		EpilBinaryExpressionCode * binary = static_cast<EpilBinaryExpressionCode*>( m_rightExpr );
		int rightPrecedence = EpilOutputHelper::GetBinaryOperatorPrecedence( binary->GetOperator() );
		if( rightPrecedence <= precedence )
		{
			isRightNeedParentheses = true;
		}
	}
	else if( m_rightExpr->GetType() == ECT_UnaryExpression )
	{
		EpilUnaryExpressionCode * unary = static_cast<EpilUnaryExpressionCode*>( m_rightExpr );
		int rightPrecedence = EpilOutputHelper::GetUnaryOperatorPrecedence( unary->GetOperator() );
		if( rightPrecedence <= precedence )
		{
			isRightNeedParentheses = true;
		}
	}
	if( isRightNeedParentheses )
	{
		ret << t("( ");
		ret << m_rightExpr->ToEpilCode();
		ret << t(" )");
	}
	else
	{
		ret << m_rightExpr->ToEpilCode();
	}

	return ret.str();
}